//    Copyright (C) Kherty.  All rights reserved.
#region

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using OpenLS.UI.Internals;

#endregion

namespace OpenLS.UI
{
    /// <summary>
    /// Represents an numeric updown control
    /// </summary>
    [TemplatePart(Type = typeof (RepeatButton), Name = DecreasePart)]
    [TemplatePart(Type = typeof (RepeatButton), Name = IncreasePart)]
    [TemplatePart(Type = typeof (TextBox), Name = TextBoxPart)]
    public class NumericUpDown : RangeBase
    {
        private const string DecreasePart = "Decrease_Part";
        private const string IncreasePart = "Increase_Part";
        private const string TextBoxPart = "TextBox_Part";

        public static readonly DependencyProperty FormatProperty =
            DependencyProperty.Register("Format", typeof (string), typeof (NumericUpDown), new UIPropertyMetadata("{0}"));

        private RepeatButton _decreaseButton;
        private RepeatButton _increaseButton;
        private TextBox _textBox;

        static NumericUpDown()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof (NumericUpDown),
                                                     new FrameworkPropertyMetadata(typeof (NumericUpDown)));
        }

        public string Format
        {
            get { return (string) GetValue(FormatProperty); }
            set { SetValue(FormatProperty, value); }
        }

        private RepeatButton increaseButton
        {
            get { return _increaseButton; }
            set
            {
                if (_increaseButton != null)
                    _increaseButton.Click -= increaseButton_Click;
                _increaseButton = value;
                if (_increaseButton != null)
                    _increaseButton.Click += increaseButton_Click;
            }
        }

        private RepeatButton decreaseButton
        {
            get { return _decreaseButton; }
            set
            {
                if (_decreaseButton != null)
                    _decreaseButton.Click -= decreaseButton_Click;
                _decreaseButton = value;
                if (_decreaseButton != null)
                    _decreaseButton.Click += decreaseButton_Click;
            }
        }


        private void increase()
        {
            var num = Math.Min(Value + SmallChange, Maximum);
            if (Value != num)
            {
                Value = num;
                selectAllText();
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _textBox = (TextBox) GetTemplateChild(TextBoxPart);
            _textBox.PreviewKeyDown += onKeyDown;
            //    _textBox.TextChanged +=this.onTextChanged;
            _textBox.LostFocus += textBox_LostFocus;
            connect();
            // _textBox.PreviewKeyDown += textBox_KeyDown;
            increaseButton = (RepeatButton) GetTemplateChild(IncreasePart);
           // increaseButton.Click += increaseButton_Click;
            decreaseButton = (RepeatButton) GetTemplateChild(DecreasePart);
           // decreaseButton.Click += decreaseButton_Click;
        }

        private void decreaseButton_Click(object sender, RoutedEventArgs e)
        {
            decrease();
        }

        private void increaseButton_Click(object sender, RoutedEventArgs e)
        {
            increase();
        }

        private void textBox_LostFocus(object sender, RoutedEventArgs e)
        {
            var s = _textBox.Text;
            onTextChanged(s);
            connect();
        }

        private void onTextChanged(string s)
        {
            var format = Format;
            var i = format.IndexOf('{');
            var j = format.IndexOf('}');
            var before = "";
            if (i > 0)
                before = format.Substring(0, i);
            var after = "";
            if (j < format.Length)
                after = format.Substring(j + 1, format.Length - j - 1);
            var numFormat = format.Substring(i, j - i + 1);
            double multiplier = 1;
            if (numFormat.Contains("%"))
                multiplier = 0.01;
            format = before + after;
            foreach (var cc in format)
                s = s.Replace(cc.ToString(), "");
            double d;
            if (double.TryParse(s, out d))
            {
                Value = d*multiplier;
            }
            // args.Handled = true;
        }


        private void connect()
        {
            var i = _textBox.CaretIndex;
            var b = new MultiBinding {Mode = BindingMode.OneWay, Converter = new FormattingConverter()};
            b.Bindings.Add(new Binding
                               {
                                   Path = new PropertyPath("Value"),
                                   RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent)
                               });
            b.Bindings.Add(new Binding
                               {
                                   Path = new PropertyPath("Format"),
                                   RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent)
                               });
            _textBox.SetBinding(TextBox.TextProperty, b);
            _textBox.CaretIndex = i;
        }


        private void onKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Up:
                    increase();
                    break;
                case Key.Down:
                    decrease();
                    break;
                case Key.Escape:
                    connect();
                    _textBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                    e.Handled = true;
                    break;
                case Key.Enter:
                    _textBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                    e.Handled = true;
                    break;
            }
        }


        private void selectAllText()
        {
            var tb = _textBox;
            tb.SelectAll();
        }

        private void decrease()
        {
            var num = Math.Max(Value - SmallChange, Minimum);
            if (Value != num)
            {
                Value = num;
                selectAllText();
            }
        }


        //public static readonly RoutedCommand Increase = new RoutedCommand("Increase", typeof(UpDown));
        //public static readonly RoutedCommand Decrease = new RoutedCommand("Decrease", typeof(UpDown));
    }
}